import os
import hashlib
from loguru import logger
import configparser
from telethon import TelegramClient, events
from asyncio import sleep
import time
from redis.asyncio import from_url
import asyncio
from telethon import functions

logger.add("robot.log", rotation="00:00")  # 每天归档


class TGRobot(object):
    """
    电报机器人
    """

    def __init__(self):

        self.redis_client = from_url(
            "redis://127.0.0.1:6379/",
            max_connections=1000,
            encoding="utf8",
            decode_responses=True,
        )

        self.config_md5 = None
        self.api_id = None
        self.api_hash = None
        self.keywords = None
        self.relay_group_list = None
        self.black_list = None
        self.white_list = None
        self.black_keywords = None
        self.content_length = None
        self.open_bot = None
        self.bot_token = None
        self.bot_name = None
        self.open_proxy = None
        self.forward_time = 300

        # 设置代理
        self.proxy = {
            'proxy_type': 'http',
            'addr': '127.0.0.1',
            'port': 7890
        }

        self.refresh_init_conf()
        # 监听session文件
        self.session_name = "default_session"
        # 机器人session文件
        self.bot_session_name = "bot_session"

        # 创建 Telegram 客户端
        self.client = TelegramClient(self.session_name, self.api_id, self.api_hash, timeout=60, proxy=self.proxy if self.open_proxy else None)
        self.client.start()

        # 创建 bot 客户端
        self.bot_client = TelegramClient(self.bot_session_name, self.api_id, self.api_hash, timeout=60, proxy=self.proxy if self.open_proxy else None)
        self.bot_client.start(bot_token=self.bot_token)

        # 转发群实例列表
        self.group_entity_list = []

        # 机器人转发群实例列表
        self.bot_group_entity_list = []

    def refresh_init_conf(self):
        """
        刷新配置
        :return:
        """
        self.config_md5 = self.get_file_md5("config.ini")
        self.api_id = int(self.get_config("api_id")) if self.get_config("api_id") else None
        self.api_hash = self.get_config("api_hash")
        self.keywords = [item for item in self.get_config("keywords").strip().split("|") if item]
        self.relay_group_list = [int(item) for item in self.get_config("relay_group_list").strip().split("|") if item]
        self.black_list = [item for item in self.get_config("black_list").strip().split("|") if item]
        self.white_list = [item for item in self.get_config("white_list").strip().split("|") if item]
        self.black_keywords = [item for item in self.get_config("black_keywords").strip().split("|") if item]
        self.content_length = int(self.get_config("content_length")) if self.get_config("content_length") else 30
        self.open_bot = bool(int(self.get_config("open_bot")))
        self.open_proxy = bool(int(self.get_config("open_proxy")))
        self.forward_time = int(self.get_config("forward_time"))
        self.bot_token = self.get_config("bot_token")
        self.bot_name = self.get_config("bot_name")

    async def check_conf_change(self):
        """检查配置文件"""

        while True:
            _config_md5 = self.get_file_md5("config.ini")
            if self.config_md5 != _config_md5:
                logger.info("更新了配置文件")
                # 刷新配置文件
                self.refresh_init_conf()
            await sleep(5)

    @staticmethod
    def get_config(key, section='Telegram'):
        """
        获取配置项
        :param section:
        :param key:
        :return:
        """
        # 创建 ConfigParser 对象
        config = configparser.ConfigParser()
        # 读取 INI 文件
        config.read('config.ini', encoding="utf8")
        return config.get(section, key)

    @staticmethod
    def get_file_md5(file_path):
        if not os.path.isfile(file_path):
            logger.error("File not found")
            raise Exception("File not found")
        md5_hash = hashlib.md5()
        with open(file_path, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):
                md5_hash.update(chunk)
        return md5_hash.hexdigest()

    async def listen_message(self):
        """
        监听群消息
        """
        logger.info(f"Listening for messages containing {self.keywords} ...")

        for group_id in self.relay_group_list:
            try:
                group_entity = await self.client.get_entity(group_id)
                self.group_entity_list.append(group_entity)
            except Exception as e:
                pass

            try:
                bot_group_entity = await self.bot_client.get_entity(group_id)
                self.bot_group_entity_list.append(bot_group_entity)
            except Exception as e:
                pass

        @self.client.on(events.NewMessage(incoming=True))
        async def handle_new_message(event):
            # 去除所有换行和空格
            message_text = event.message.message.replace(" ", "").replace("\n", "").replace("\r", "")
            sender = await event.get_sender()
            # 不处理机器人信息
            if not sender or not hasattr(sender, 'bot') or sender.bot:
                return
            # 不处理没有用户名的信息
            if not sender.username:
                return
            # 获取发送人的名称
            sender_username = str(sender.username)
            # 不处理黑名单用户
            if sender_username in self.black_list:
                logger.info(f"{sender_username} 为黑名单用户")
                return
            # 不处理大于文件限制的信息和不在白名单的信息
            if len(message_text) >= self.content_length and sender_username not in self.white_list:
                logger.info(f"{sender_username} 消息限制，并且不在白名单")
                return

            for _keyword in self.black_keywords:
                if _keyword in message_text:
                    return

            if self.keywords:
                for keyword in self.keywords:
                    if keyword in message_text:
                        message =f"📣原文消息\n{message_text}\n㊙️来源用户\n@{sender_username}"
                        if await self.redis_client.set(f"lock_{sender.id}", 'locked', ex=self.forward_time, nx=True):
                            if not self.open_bot:
                                for _group_entity in self.group_entity_list:
                                    logger.info(f"匹配到关键词 {message} 已发送到 {_group_entity.title}")
                                    await self.client.send_message(_group_entity, message)
                            else:
                                entity = await self.client.get_entity(self.bot_name)
                                await self.client.send_message(entity, message + "@robot_msg")

                        else:
                            logger.info(f"用户{sender.username} 5分钟内已发送过信息")
                        return
            else:
                message = f"📣原文消息\n{message_text}\n㊙️来源用户\n@{sender_username}"
                if await self.redis_client.set(f"lock_{sender.id}", 'locked', ex=self.forward_time, nx=True):
                    if not self.open_bot:
                        for _group_entity in self.group_entity_list:
                            logger.info(f"匹配到关键词 {message} 已发送到 {_group_entity.title}")
                            await self.client.send_message(_group_entity, message)
                    else:
                        entity = await self.client.get_entity(self.bot_name)
                        await self.client.send_message(entity, message + "@robot_msg")

                else:
                    logger.info(f"用户{sender.username} 5分钟内已发送过信息")

        @self.bot_client.on(events.NewMessage(incoming=True))
        async def handle_bot_new_message(event):
            # 去除所有换行和空格
            message_text = event.message.message
            if '@robot_msg' in message_text:
                logger.info(f"机器人收到消息啦：{message_text}")
                for _group_entity in self.bot_group_entity_list:
                    await self.bot_client(functions.messages.SendMessageRequest(
                        peer=_group_entity,
                        message=message_text.replace('@robot_msg', '')
                    ))

        tasks = [
            self.client.run_until_disconnected(),
            self.check_conf_change(),
        ]
        await asyncio.gather(*tasks)


loop = asyncio.get_event_loop()
loop.run_until_complete(TGRobot().listen_message())
